package com.shensi.adminCollect.service.station.impl;

import com.alibaba.fastjson.JSONObject;
import com.shensi.common.core.domain.model.LoginUser;
import com.shensi.common.core.exception.BaseException;
import com.shensi.common.core.exception.CustomException;
import com.shensi.common.core.utils.MathUtil;
import com.shensi.common.core.utils.SecurityUtils;
import com.shensi.common.core.utils.StringUtils;
import com.shensi.adminCollect.domain.station.*;
import com.shensi.adminCollect.domain.station.dto.PhysicalCardBalanceListDto;
import com.shensi.adminCollect.domain.station.dto.PhysicalCardListDto;
import com.shensi.adminCollect.domain.station.dto.PhysicalCardSecretKeyDto;
import com.shensi.adminCollect.enums.station.BalanceTypeEnum;
import com.shensi.adminCollect.enums.station.PhysicalCardPaymentEnum;
import com.shensi.adminCollect.mapper.station.PayWayMapper;
import com.shensi.adminCollect.mapper.station.PhysicalCardBalanceMapper;
import com.shensi.adminCollect.mapper.station.PhysicalCardMapper;
import com.shensi.adminCollect.mapper.station.StationMapper;
import com.shensi.adminCollect.service.station.IPayOrderService;
import com.shensi.adminCollect.service.station.IPhysicalCardBalanceService;
import com.shensi.adminCollect.domain.system.SysRespon;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service("physicalCardBalanceServiceImpl")
@Slf4j
public class PhysicalCardBalanceServiceImpl implements IPhysicalCardBalanceService {

    @Autowired
    private PhysicalCardMapper physicalCardMapper;

    @Autowired
    private PhysicalCardBalanceMapper physicalCardBalanceMapper;

    @Autowired
    private StationMapper stationMapper;

    @Autowired
    private PayWayMapper payWayMapper;

    @Autowired
    private IPayOrderService payOrderService;

    @Value("${qujia.payBaseUrl}")
    private String payBaseUrl;

    @Override
    public PhysicalCardSecretKeyDto addPhysicalCardBalance(PhysicalCardBalance physicalCardBalance) {
        if(Objects.isNull(physicalCardBalance) || StringUtils.isEmpty(physicalCardBalance.getPhysicalCardNo())){
            throw new BaseException("qujia-customer","PhysicalCardBalanceServiceImpl实体卡充值数据异常");
        }

        if(StringUtils.isEmpty(physicalCardBalance.getStationId())){
            throw new BaseException("实体卡充值--油站不存在");
        }

        Station station = stationMapper.selectStationById(Long.valueOf(physicalCardBalance.getStationId()));
        physicalCardBalance.setStationName(station.getStationName());


        // 充值时才需要生成订单号  消费时订单号和订单表一致
        String balanceNo = "";
        if(BalanceTypeEnum.RECHARGE.getValue().equals(physicalCardBalance.getBalanceType())
                || BalanceTypeEnum.RATION_RECHARGE.getValue().equals(physicalCardBalance.getBalanceType())) {
            // 生成订单号
            Random random = new Random();
            String result = "";
            for (int i = 0; i < 6; i++) {
                result += random.nextInt(10);
            }
            balanceNo = System.currentTimeMillis() + result;
            physicalCardBalance.setBalanceNo(balanceNo);
        }
        physicalCardBalance.setCreateTime(new Date());
        log.info("实体卡充值，PhysicalCardBalanceServiceImpl.addPhysicalCardBalance: [{}]", JSONObject.toJSONString(physicalCardBalance));
        physicalCardBalanceMapper.insertSelective(physicalCardBalance);



        PhysicalCardSecretKeyDto physicalCardSecretKeyDto = new PhysicalCardSecretKeyDto();
        physicalCardSecretKeyDto.setOrderNo(balanceNo);
        return physicalCardSecretKeyDto;
    }

    @Override
    public List<PhysicalCardBalanceListDto> selectPhysicalCardBalanceList(PhysicalCardBalanceListDto physicalCardBalanceListDto) {
        // 充值记录也会绑定多个油站， 油站id 和 油站名按照 , 拼接
        List<PhysicalCardBalanceListDto> balanceListDtos = physicalCardBalanceMapper.selectPhysicalCardBalanceList(physicalCardBalanceListDto);
        for (PhysicalCardBalanceListDto balanceListDto : balanceListDtos) {
            PhysicalCard physicalCard = physicalCardMapper.selectPhysicalCardByNo(balanceListDto.getPhysicalCardNo());
            balanceListDto.setPhysicalCardType(physicalCard.getPhysicalCardType());
        }

        return balanceListDtos;
    }


    @Override
    public int updatePhysicalCardBalance(PhysicalCardBalance physicalCardBalance) {
        int i = 0;
        if(Objects.nonNull(physicalCardBalance) || StringUtils.isNotEmpty(physicalCardBalance.getBalanceNo())){
            i = physicalCardBalanceMapper.updateByPrimaryKeySelective(physicalCardBalance);
        }
        if(i <= 0){
            throw new BaseException("实体卡消费订单撤销失败：[{}]",JSONObject.toJSONString(physicalCardBalance));
        }
        return i;
    }

    @Override
    @Transactional
    public Long posRechargeRefund(Long id) {
        PhysicalCardBalance rechargeRecord = physicalCardBalanceMapper.getById(id);
        if (rechargeRecord == null || !StringUtils.equalsAny(rechargeRecord.getPayment(),PhysicalCardPaymentEnum.POS.getValue(), PhysicalCardPaymentEnum.WX_RECHARGE.getValue())) {
            throw new CustomException("订单不支持退款");
        }
        if (!StringUtils.equals("1",rechargeRecord.getRefundStatus())) {
            throw new CustomException("订单已退款");
        }
        PhysicalCard physicalCard = physicalCardMapper.selectByPhysicalCardNo(rechargeRecord.getPhysicalCardNo());
        if (physicalCard == null) {
            throw new CustomException("实体卡不存在");
        }
        PayWay payWay = payWayMapper.selectPayWayById(rechargeRecord.getPayWayId());
        if (payWay == null) {
            throw new CustomException("支付渠道未找到");
        }
        BigDecimal balance = physicalCard.getPhysicalCardAmount();
        BigDecimal newBalance = MathUtil.subtract(balance, rechargeRecord.getAmount());
        if (newBalance.compareTo(BigDecimal.ZERO)<0) {
            throw new CustomException("余额不足");
        }
        PhysicalCard pcUpdate = new PhysicalCard();
        pcUpdate.setId(physicalCard.getId());
        pcUpdate.setPhysicalCardAmount(newBalance);
        physicalCardMapper.updateById(pcUpdate);
        PhysicalCardBalance pcbUpdate = new PhysicalCardBalance();
        pcbUpdate.setId(rechargeRecord.getId());
        pcbUpdate.setRefundStatus("2");
        physicalCardBalanceMapper.updateById(pcbUpdate);
        PhysicalCardBalance refundRecord = insertRefundRecord(rechargeRecord,newBalance);
        doRefund(rechargeRecord,refundRecord,payWay);
        return refundRecord.getId();
    }

    private PhysicalCardBalance insertRefundRecord(PhysicalCardBalance rechargeRecord,BigDecimal balance){
        PhysicalCardBalance refundRecord = new PhysicalCardBalance();
        refundRecord.setBalanceNo(StringUtils.generateOrdNo());
        refundRecord.setPhysicalCardNo(rechargeRecord.getPhysicalCardNo());
        refundRecord.setAmount(rechargeRecord.getAmount());
        refundRecord.setBalanceAmount(balance);
        refundRecord.setBalanceType(rechargeRecord.getBalanceType());
        refundRecord.setEnterpriseId(rechargeRecord.getEnterpriseId());
        refundRecord.setEnterpriseName(rechargeRecord.getEnterpriseName());
        refundRecord.setStationId(rechargeRecord.getStationId());
        refundRecord.setStationName(rechargeRecord.getStationName());
        refundRecord.setStatus("0");
        refundRecord.setCreateTime(new Date());
        refundRecord.setIsDeleted("0");
        refundRecord.setPayment(PhysicalCardPaymentEnum.REFUND.getValue());
        refundRecord.setRefundStatus("1");
        refundRecord.setPayWayId(rechargeRecord.getPayWayId());
        refundRecord.setServiceCharge(rechargeRecord.getServiceCharge());
        LoginUser user = SecurityUtils.getLoginUser();
        refundRecord.setOperator(Math.toIntExact(user.getUser().getUserId()));
//        physicalCardBalanceMapper.insertSelective(refundRecord);
        return refundRecord;
    }

    private void doRefund(PhysicalCardBalance rechargeRecord, PhysicalCardBalance refundRecord, PayWay payWay){
        SysRespon sysRespon;
        String thirdOrderNo= null;
        String thirdPayNo = null;
        String payType = payWay.getPayType();
        switch (payType){
            case "1":  //随行付
                sysRespon = sxfRefund(rechargeRecord,refundRecord, payWay);
                if (sysRespon != null) {
                    if (sysRespon.getData() != null) {
                        HashMap<String, Object> data = (HashMap<String, Object>) sysRespon.getData();
                        thirdOrderNo = (String) data.get("uuid");
                    }
                    String code = sysRespon.getResponCode();
                    if (StringUtils.equalsAny(code,"0000","2002")) {
                        callBackForRefundSuccess(rechargeRecord,refundRecord);
                    }else {
                        sysRespon = null;
                    }
                }
                break;
            case "5":  // 云化支付
                sysRespon = yunhuaRefund(rechargeRecord,refundRecord, payWay);
                if (sysRespon != null) {
                    if (sysRespon.getData() != null) {
                        JSONObject data = (JSONObject) sysRespon.getData();
                        thirdOrderNo = data.getString("refundTransInfoNo");
                        thirdPayNo = data.getString("refundTransPayNo");
                    }
                    if (StringUtils.equals("0000",sysRespon.getResponCode())) {
                        callBackForRefundSuccess(rechargeRecord,refundRecord);
                    }else{
                        sysRespon = null;
                    }
                }
                break;
            default:
                throw new CustomException("不支持的支付渠道");
        }
        if (sysRespon == null) {
            //callBackForRefundFail(refundRecord,thirdOrderNo,thirdPayNo);
            log.error("退款失败");
            throw new CustomException("退款失败");
        }
    }

    private SysRespon sxfRefund(PhysicalCardBalance rechargeRecord, PhysicalCardBalance refundRecord, PayWay payWay){
        try {
            return payOrderService.sendSxfRefundOrder(refundRecord.getAmount(), refundRecord.getBalanceNo(),rechargeRecord.getBalanceNo(), payWay.getMno());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    private SysRespon yunhuaRefund(PhysicalCardBalance rechargeRecord, PhysicalCardBalance refundRecord, PayWay payWay){
        try {
            PayOrder payOrder = new PayOrder();
            payOrder.setAmt(refundRecord.getAmount());
            payOrder.setReceivedAmt(refundRecord.getAmount());
            payOrder.setOrderNo(rechargeRecord.getBalanceNo());
            payOrder.setMerchantsNumber(rechargeRecord.getMerchantsNumber());
            payOrder.setTransactionId(rechargeRecord.getTransactionId());
            payOrder.setPayWayId(rechargeRecord.getPayWayId());
            payOrder.setStationId(Long.valueOf(rechargeRecord.getStationId()));
            payOrder.setPayDate(rechargeRecord.getCreateTime());
            return payOrderService.yunHuaRefundV2(refundRecord.getBalanceNo(),payOrder, payWay);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    private void callBackForRefundSuccess(PhysicalCardBalance rechargeRecord, PhysicalCardBalance refundRecord){
        log.info("实体卡充值退款成功回调，refundOrderNo:{}",refundRecord.getBalanceNo());
//        PhysicalCardBalance refundUpdate = new PhysicalCardBalance();
//        refundUpdate.setId(refundRecord.getId());
//        refundUpdate.setStatus("1");
//        physicalCardBalanceMapper.updateById(refundUpdate);
        //CustomerCardUseRecord refundUseRecord = customerCardUseRecordService.selectCustomerCardUseRecordById(refundRecorde.getRefundRecordId());
        PhysicalCardBalance rechargeUpdate = new PhysicalCardBalance();
        rechargeUpdate.setId(rechargeRecord.getId());
        rechargeUpdate.setRefundStatus("3");
        physicalCardBalanceMapper.updateById(rechargeUpdate);
        log.info("实体卡充值退款成功回调-成功，refundOrderNo:{}",refundRecord.getBalanceNo());
        //退款打印小票
        //orderPrintService.printRefundElectrondOrder(refundUseRecord,refundRecorde);

    }

    @Override
    public PhysicalCardBalanceListDto selectPhysicalCardBalanceStatistics(PhysicalCardBalanceListDto physicalCardBalanceListDto) {
        log.info("selectPhysicalCardBalanceStatistics 请求参数：[{}]",JSONObject.toJSONString(physicalCardBalanceListDto));

        // 实体卡充值总计
        BigDecimal totalRechargeAmt = BigDecimal.ZERO;
        // 实体卡消费总计
        BigDecimal totalConsumptionAmt = BigDecimal.ZERO;
        //退款
        BigDecimal totalRefundAmt = BigDecimal.ZERO;
        // 实体卡余额总计
        BigDecimal totalBalanceAmt = BigDecimal.ZERO;

        PhysicalCardListDto physicalCardListDto = new PhysicalCardListDto();
        if(Objects.nonNull(physicalCardBalanceListDto)){
            physicalCardListDto.setEnterpriseId(physicalCardBalanceListDto.getEnterpriseId());
            physicalCardListDto.setStationId(physicalCardBalanceListDto.getStationId());
            physicalCardListDto.setPhysicalCardNo(physicalCardBalanceListDto.getPhysicalCardNo());
            physicalCardListDto.setUserPhone(physicalCardBalanceListDto.getUserPhone());
            physicalCardListDto.setUserName(physicalCardBalanceListDto.getUserName());
        }
        totalBalanceAmt = physicalCardMapper.selectTotalBalanceAmt(physicalCardListDto);

        List<PhysicalCardBalanceListDto> balanceListDtos = physicalCardBalanceMapper.selectPhysicalCardBalanceList(physicalCardBalanceListDto);
        if(CollectionUtils.isEmpty(balanceListDtos)){
            PhysicalCardBalanceListDto physicalCardBalance = new PhysicalCardBalanceListDto();
            physicalCardBalance.setTotalRechargeAmt(totalRechargeAmt);
            physicalCardBalance.setTotalConsumptionAmt(totalConsumptionAmt);
            physicalCardBalance.setTotalBalanceAmt(totalBalanceAmt);
            log.info("selectPhysicalCardBalanceStatistics 未查询到结果");
            return physicalCardBalance;
        }

        for (PhysicalCardBalanceListDto balanceListDto : balanceListDtos) {
            if(BalanceTypeEnum.RECHARGE.getValue().equals(balanceListDto.getBalanceType()) || BalanceTypeEnum.RATION_RECHARGE.getValue().equals(balanceListDto.getBalanceType())){
                if(!"3".equals(balanceListDto.getRefundStatus()) && !PhysicalCardPaymentEnum.REFUND.getValue().equals(balanceListDto.getPayment())) {
                    totalRechargeAmt = totalRechargeAmt.add(Objects.nonNull(balanceListDto.getAmount()) ? balanceListDto.getAmount() : BigDecimal.ZERO);
                }
            }

            if(BalanceTypeEnum.CONSUMPTION.getValue().equals(balanceListDto.getBalanceType()) || BalanceTypeEnum.RATION_CONSUMPTION.getValue().equals(balanceListDto.getBalanceType())){
                totalConsumptionAmt = totalConsumptionAmt.add(Objects.nonNull(balanceListDto.getAmount()) ? balanceListDto.getAmount() : BigDecimal.ZERO);
            }

            if(PhysicalCardPaymentEnum.REFUND.getValue().equals(balanceListDto.getPayment())){
                totalRefundAmt = totalRefundAmt.add(Objects.nonNull(balanceListDto.getAmount()) ? balanceListDto.getAmount() : BigDecimal.ZERO);
            }
        }

        PhysicalCardBalanceListDto physicalCardBalance = new PhysicalCardBalanceListDto();
        physicalCardBalance.setTotalRechargeAmt(totalRechargeAmt);
        physicalCardBalance.setTotalConsumptionAmt(totalConsumptionAmt);
        physicalCardBalance.setTotalBalanceAmt(totalBalanceAmt);
        log.info("selectPhysicalCardBalanceStatistics 返回结果：[{}]",JSONObject.toJSONString(physicalCardBalance));
        return physicalCardBalance;
    }

}
